import io
import logging

from django.contrib.auth.models import User
from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
from rest_framework.permissions import IsAuthenticated
from rest_framework.status import HTTP_404_NOT_FOUND,HTTP_400_BAD_REQUEST,HTTP_500_INTERNAL_SERVER_ERROR

from config.dbs.redis_rev import LOGIN_KEY_TEMPLATE, EXPIRE_TIME
from users.models import UserDetail, Area
from users.serializers import UserSerializer, UserDetailSerializer, UpdatePasswordSerializer, AreaSerializer,ParentSerializer,AddressSerializer
from utils.permission import ActiveUserPermission, wrap_permission, TeacherPermission, RootPersion, update_auto_user, \
    destroy_auto_user, auto_user
from utils.verifyUtil import ImageVerify
from config.fastdfsConfig import FASTDFS_SERVER_DOMAIN
from fdfs_client.client import Fdfs_client,get_tracker_conf
from rest_framework_extensions.cache.mixins import CacheResponseMixin

#导入日志器
logger = logging.getLogger(__name__)
#tracker server
tracker_path = get_tracker_conf('utils/fastdfs/client.conf')
client = Fdfs_client(tracker_path)


class ImageVerifyView(View):
    """
    图片验证码的视图类
    get
    返回图片验证码
    """
    def get(self,request,uuid):  #uuid设备唯一识别码，，，用它来判断是哪一个设备发起了请求
        """
        返回图片验证码
        :param request: 请求对象
        :param uuid: 客户端唯一识别码
        :return:
        """
        imgVerify =ImageVerify() #生成验证码
        img, code = imgVerify.verify_code()

        #将图片数据返回给客户端，无需持久化，使用文件流(因为每用一次生成一张图片太占地方)，因为是图片，是字节数据
        img_bytes = io.BytesIO() #生成字节的临时文件流
        img.save(img_bytes,format='PNG') #图片保存，把数据放进去,类型是PNG
        image_bytes = img_bytes.getvalue() #图片字节数据，获取当前图片

        #如何保存  格式：uuid:aW8i(验证码)(key-value) 临时数据中，缓存到redis中
        cache = get_redis_connection(alias='verify_codes') #获取连接池，redis连接操作，里面连接池alias是哪一个
        cache.set(LOGIN_KEY_TEMPLATE % uuid,code,EXPIRE_TIME) #把内容保存到redis，设置一下配置,像过期时间这些

        return HttpResponse(image_bytes,content_type='image/png') #返回的数据是字节数据,格式是图片拼接格式


class UserViewSet(ReadOnlyModelViewSet):
    queryset = User.objects.filter(is_active=1)  # 查看用户详情状态是否在启用，1表示启用，不写is_delete=False是因为从用户去查看详情表，而用户已经筛选过了
    serializer_class = UserSerializer  # 序列化器数据从哪来，就写谁
    permission_classes = [IsAuthenticated]  # 表示你必须是登陆的状态才能使用详情的功能

    def get_serializer(self, *args, **kwargs):
        if self.action == 'password':
            return UpdatePasswordSerializer(*args, **kwargs)
        return self.serializer_class(*args, **kwargs)

    @wrap_permission(TeacherPermission)
    def list(self, request, *args, **kwargs): #查看所有人，只有老师才能查看
        return ReadOnlyModelViewSet.list(self, request, *args, **kwargs)

    @wrap_permission(ActiveUserPermission)
    def retrieve(self, request, *args, **kwargs):  #查询单个人的信息
        return ReadOnlyModelViewSet.retrieve()

    @wrap_permission(ActiveUserPermission)
    def update(self,request,pk): #个人信息修改(只有自己才能修改自己的信息)
        #得到用户 user
        try:
            user = self.get_queryset().get(id=pk)
        except User.DoesNotExist : #如果不存在,返回404
            return Response(status=HTTP_404_NOT_FOUND)
        #把得到的用户输入的数据进行反序列化(把json数据转为模型类数据)
        user_serializer = self.get_serializer(user,data=request.data) #后面是前端传过来的数据
        #数据校验
        user_serializer.is_valid(raise_exception=True)
        #修改user表信息
        user_serializer.save()
        #判断用户是否传入详情数据，而不是只添加一个用户
        user_detail = request.data.get('userdetail') #获取用户传入的详情数据
        if user_detail:
            # 是，判断数据库中是否有用户以前的详情数据
            if hasattr(user,'userdetail'):
                # 有，修改
                user_detail_serializer = UserDetailSerializer(user.userdetail,data=user_detail) #修改，进行序列化，展示到前端
            else:
                #无，增加
                user_detail['user'] = pk #制定用户，给详情数据保定一个id
                user_detail_serializer = UserDetailSerializer(data=user_detail) #不传源数据就增加

            user_detail_serializer.is_valid(raise_exception=True)
            user_detail_serializer.save()

            user_serializer.data['userdetail'] = UserDetailSerializer(data=user_detail)
        #返回修改后的数据
        return Response(user_serializer.data)

    @action(methods=['post'],detail=True)
    def avatar(self,request,pk):
        #获取需要操作的用户
        try:
            user = self.get_queryset().get(id=pk)
        except User.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        #得到上传的文件数据
        file = request.FILES.get('file')
        #判断是否是图片数据，文件类型是否是图片
        if not file or file.content_type not in ('image/png','image/jpeg','image.gif'):
            #不是图片，返回客户端输出错误数据
            return Response(status=HTTP_400_BAD_REQUEST)
        #是图片，交给fastdfs，存储到可用的storage服务上
        #得到文件后缀名，如果没有默认用png
        try:
            images_ext_name = file.name.split('.')[-1]
        except Exception as e:
            logger.info('图片拓展名异常： %s' %e)
            images_ext_name = 'png'
        #上传图片数据，通过字节流
        try:
            upload_res = client.upload_by_buffer(file.read(),file_ext_name=images_ext_name) #读取发过来的图片内容，文件名为刚才的文件名
        except Exception as e:
            logger.error('图片上传异常：%s'%e)
            return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)
        else:
            if upload_res.get('Status') != 'Upload successed.':
                logger.warning('图片上传失败：')
                return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)
            #得到返回的file_id
            image_name = upload_res.get('Remote file_id').decode()
            image_url = FASTDFS_SERVER_DOMAIN + image_name  #拼接路径
            #判断用户是否有详情数表数据
            if hasattr(user,'userdetail'):
                #有，修改头像字段，保存图片信息、
                user_detail = user.userdetail  #获得用户的详情信息
                user_detail.avatar = image_url  #把图片路径拼接到用户详情里面
                user_detail.save()
            else:
                # 没有，创建详情，保存图片信息
                UserDetail.objects.create(avatar=image_url,user=user) #创建，把图像给进去，然后把用户给进去
        #返回头像的图片地址
        return Response({'data':image_url})

    @action(methods=['put'],detail=True)
    def password(self,request,pk):  #修改密码
        #获取需要操作的用户
        try:
            user = self.get_queryset().get(id=pk)
        except User.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        #检查给过来的原密码是否正确
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        password = request.data['password'] #得到客户端输入的原密码
        new_password = request.data['new_password'] #得到用户输入的新密码
        if user.check_password(password): #检查一下原密码是否是正确的
            #正确，修改密码
            user.set_password(new_password)
            user.save()
            return Response({'msg':'修改成功'})
        else:
            #错误，返回提示，原密码错误
            return Response(status=HTTP_400_BAD_REQUEST)

class AreaViewSet(CacheResponseMixin,ModelViewSet):
    queryset = Area.objects.all()
    serializer_class = AreaSerializer

    def get_queryset(self): #重写
        if self.action == 'list': #如果你是直接查看
            return Area.objects.filter(parent=None) #返回没有上级行政区划的，也就是省
        else:
            return self.queryset #否则返回对应的查询数据（就是上面那第一句）

    def get_serializer_class(self): #这是新的方式，也可以老的方式：get_serializer(这里面一大堆)
        if self.action =='retrieve':
            #如果是单条操作，查看单个省份
            return ParentSerializer #这个序列化器就是查看单个省份的所有市
        else:
            return AreaSerializer

    @wrap_permission()
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permission()
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permission()
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)

class AddressViewSet(ModelViewSet):
    serializer_class = AddressSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.request.user.address_set.filter(is_delete=False)

    @auto_user
    def create(self, request, *args, **kwargs):
        max_count = 10 #设最多创建多少条
        if self.get_queryset().count() >= max_count: #如果创建的数量大于设置的最大数量
            return Response({'detail':f'收货地址数量超出了{max_count}条上限'},status=HTTP_400_BAD_REQUEST)#不正常的话返回404
        return ModelViewSet.create(self, request, *args, **kwargs)

    @update_auto_user
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @destroy_auto_user
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)



